package com.pj.lib.auraClient;



import java.io.IOException;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.io.StreamCorruptedException;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;


import java.util.Properties;

import com.pj.lib.aura.connection.NetworkMap;

import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
import android.util.Log;



/**
 * Klasa (Singleton) sluzaca do komunikowania sie z serwerem - laczenie, rozlaczenie, wysylanie (odbieranie wiadomosci znajduje sie w serwisie {@link NetworkService}. 
 * @author Pawel Janeczek
 * @version 0.3
 */
public class AuraConnection {
	static final String TAG ="AuraConnection";
	
	private static AuraConnection ac;
	private Socket s;

	private ObjectInputStream ois = null;
	private ObjectOutputStream oos = null;
	
	/**
	 * Metoda sluzaca do pobierania instacji AuraClient (jesli taka jeszcze nie istnieje to tworzy nowy obiekt klasy AuraClient.
	 * @return Instancja AuraClient
	 */
	public static AuraConnection getInstance() {
		if(ac == null) {
			ac = new AuraConnection();
		}
		return ac;
	}
	
	/**
	 * Funkcja sluzaca do laczenia sie z serwerem.
	 * @param props Ustawienia serwera. Posiada dwie wartosci (klucze): AuraClient.SERVER_ADDRESS (jest to adres ip serwera) oraz AuraClient.SERVER_PORT (port serwera); 
	 * @throws NumberFormatException
	 * @throws UnknownHostException
	 * @throws IOException
	 * @throws SocketException
	 */
	public void connect(String serverAddress, int serverPort) throws NumberFormatException, UnknownHostException, IOException, SocketException {
		if(Aura.DEBUG) {
			Log.i(TAG, "connecting to server with: " + serverAddress + " " + serverPort);
		}
		s = new Socket(serverAddress, serverPort);

		oos = new ObjectOutputStream(s.getOutputStream());
		ois = new ObjectInputStream(s.getInputStream());


        if(Aura.DEBUG) {
			Log.i(TAG, "connected to server");
		}
	}
	
	/**
	 * Zwraca obiekt klasy {@link ObjectOutputStream}.
	 * @return Obiekt klasy {@link ObjectOutputStream} sluzacy do wysylania na serwer.
	 */
	public ObjectOutputStream getOut(){
		return oos;
	}
	
	/**
	 * Zwraca obiekt klasy {@link ObjectInputStream}.
	 * @return Obiekt klasy {@link ObjectInputStream} sluzacy do odbierania wiadomosci z serwera.
	 */
	public ObjectInputStream getIn() {
		return ois;
	}
	
	/**
	 * Funkcja ta sluzy do pisania wiadomosci do serwera.
	 * @param map Obiekt klasy NetworkMap wraz ze wszystkim informacjami do przeslania
	 * @return True - jesli poprawnie wyslane. False - jesli nie udalo sie wyslac (brak polaczenia z serwerem).
	 * @throws IOException, NullPointerException 
	 */
	public void write(NetworkMap map) throws IOException, NullPointerException  {
		oos.writeObject(map);
		oos.flush();
	}
	

	
	/**
	 * Funkcja sluzaca do zamkniecia serwera
	 * @param res Obiekt klasy Resources z Androida - potrzebny do pobrania tekstu.
	 * @throws IOException
	 * @throws NoNetworkConnectionException
	 * @throws NotFoundException
	 */
	public void closeConnection(Resources res) throws IOException, NotFoundException {
		if(oos != null )
			oos.close();
		if(ois == null)
			ois.close();
		if(s == null)
			s.close();
	}
}
